#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8

# Copyright (c) 2025 Li Auto Inc. and its affiliates
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import ply.lex as lex
import argparse
import os


states = (
    ('cmd', 'exclusive'),
    ('path', 'exclusive'),
)

# List of token names.   This is always required
tokens = [
    'DEINIT',
    'INIT',
    'INCLUDE',
    'NOT',
    'EQUAL',
    'CONTAINS',
    'COLON',
    'SEMICOLON',
    'LEFTBRACE',
    'RIGHTBRACE',
    'PATH',
    'STRING',
    'OP_EQUAL',
    'OP_NOT_EQUAL',
    'OP_CONTAINS',
    'OP_NOT_CONTAINS',
    'AT',
    'NAME',
    'COMMA',
    'CTRL_WAIT',
    'CTRL_DEVICE',
    'CTRL_SLEEP',
    'CTRL_LD_LIB',
    'TIMEOUT',
    # 'NEWLINE',
    # 'UT',
    # 'ST',
]

t_COMMA = r','
t_COLON = r':'
t_AT    = r'@'

t_cmd_NOT = r'(not|NOT)'
t_cmd_EQUAL = r'(equal|EQUAL)'
t_cmd_CONTAINS = r'(contains|CONTAINS)'
t_cmd_OP_EQUAL = r'=='
t_cmd_OP_CONTAINS = r'~'
t_cmd_OP_NOT_EQUAL = r'!='
t_cmd_OP_NOT_CONTAINS = r'!~'
t_cmd_CTRL_WAIT = r'/(w|W|wait|WAIT)'
t_cmd_CTRL_DEVICE = r'/(d|D|device|DEVICE)'
t_cmd_CTRL_SLEEP = r'/(s|S|sleep|SLEEP)'
t_cmd_CTRL_LD_LIB = r'/(ld_lib|LD_LIB)'
t_cmd_TIMEOUT = r'[1-9]\d*'

t_cmd_STRING = r'\"(\\.|[^\\"\n])*\"'

# A string containing ignored characters (spaces and tabs)
t_ignore = ' \n\t'
t_cmd_ignore = ' \n\t'
t_path_ignore = ' \n\t'


def t_DEINIT(t):
    r'(deinit|DEINIT)'
    return t


def t_INIT(t):
    r'(init|INIT)'
    return t


def t_INCLUDE(t):
    r'(include|INCLUDE|import|IMPORT)'
    t.lexer.begin('path')
    return t


def t_path_PATH(t):
    r'[\w\./_-]+'
    return t


def t_LEFTBRACE(t):
    r'{'
    t.lexer.begin('cmd')
    return t

def t_cmd_RIGHTBRACE(t):
    r'}'
    t.lexer.begin('INITIAL')
    return t

def t_ANY_SEMICOLON(t):
    r';'
    t.lexer.begin('INITIAL')
    return t

def t_NAME(t):
    r'\w+'
    return t

def t_ANY_COMMENT(t):
    r'(/\*(.|\n)*?\*/)|(//.*)|(\#.*)'
    pass


# Error handling rule
def t_ANY_error(t):
    print("Illegal character '{0}'".format(t.value[0]))
    t.lexer.skip(1)


# Build the lexer
lexer = lex.lex()


def main():
    def read_file(path):
        try:
            f = open(path, encoding="utf-8")
            data = f.read()
            f.close()

            return data
        except FileNotFoundError as err:
            print(err)
            return None

    option = argparse.ArgumentParser(description="Compiler for Test Profile")

    option.add_argument('--verbose', '-v',
                        action='store_true', help='verbose mode')
    option.add_argument('--directory', '-c',
                        action='store', dest="topdir",
                        help='Change to directory.')
    option.add_argument('--file', '-f',
                        action='store', dest="profile",
                        help='Indicate a top profile.')

    arg = option.parse_args()
    if arg.topdir is not None:
        try:
            os.chdir(arg.topdir)
        except OSError as err:
            print("Fail to change directoy: {0}".format(err))
            sys.exit(-1)

    if arg.profile is None:
        top_profile = os.path.join(os.path.curdir, "TestProfile")
    else:
        top_profile = arg.profile
    print(top_profile)
    data = read_file(top_profile)
    if data is not None:
        lexer.input(data)
        while True:
            tok = lexer.token()
            if not tok:
                break
            print(tok)


if __name__ == "__main__":
    main()
